package com.fingard.dsp.bank.directbank.pab01;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.net.WebRequest;
import com.fingard.text.StringHelper;
import com.fingard.util.TransIDHelper;
import com.fingard.xml.XmlTextWriter;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Date;
import java.util.Map;

public class PAB01Base extends DirectBase implements ITcpClient {
    private static TransIDHelper idHelper = new TransIDHelper(1, 999);

    protected String getQryTransID() {
        Date tmpDateNow = new Date();
        return Format.DateTime12Year2Format.format(tmpDateNow) + idHelper.getNextIDStr();
    }

    protected String getCharset() {
        return getBankConfig().getCharset("GBK");
    }

    protected void writeCommonHeader(XmlTextWriter xmlWriter) {
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
    }

    protected String[] sendToBank(String p_reqStr,PAB01Header p_bankHeader,String transType,String commandCode) throws Exception {
        String[] retStr = new String[]{"", ""};
        //后置挡板
        if (StringHelper.hasAnyChar(transType) && StringHelper.hasAnyChar(commandCode)) {
            this.detailSimulateForBank(bankFront.bankCode, transType, commandCode, p_reqStr, retStr);
            if (retStr[1].length() > 0) {
                return retStr;
            }
        }
        return sendToBank(p_reqStr,p_bankHeader);
    }

    /**返回数组：[0]ConnState   [1]报文   [2]retCode  [3]retInfo*/
    protected String[] sendToBank(String p_reqStr, PAB01Header p_bankHeader) throws Exception {
        String[] tmpStrRet = new String[]{"", "", "", ""};

        if (StringHelper.isNullOrEmpty(p_bankHeader.trncode)) {
            throw new Exception("未赋值trncode");
        }
        if (StringHelper.isNullOrEmpty(p_bankHeader.reqSeqNo)) {
            throw new Exception("未赋值reqSeqNo");
        }
        if (StringHelper.isNullOrEmpty(p_bankHeader.fourZero)) {
            throw new Exception("未赋值fourZero");
        }

        // 消息报文头
        StringBuilder tmpReqMsgHead = new StringBuilder();
        tmpReqMsgHead.append("A001010101");
        String cms_corp_no = StringHelper.hasAnyChar(bankFront.org) ? bankFront.org : getBankConfig().getValueAsString("cms_corp_no");
        tmpReqMsgHead.append(String.format("%20s", cms_corp_no).replace(' ', '0')); /* 企业银企直连标准代码 */
        tmpReqMsgHead.append(String.format("%10s", p_reqStr.getBytes(getCharset()).length).replace(' ', '0')); /* 接收报文长度 */
        tmpReqMsgHead.append(String.format("%-6s", p_bankHeader.trncode)); /* 交易码 */
        tmpReqMsgHead.append("     01");
        Date tmpDateNow = new Date();
        tmpReqMsgHead.append(Format.Date8Format.format(tmpDateNow));
        tmpReqMsgHead.append(Format.Time6Format.format(tmpDateNow));
        tmpReqMsgHead.append(String.format("%20s", p_bankHeader.reqSeqNo));
        tmpReqMsgHead.append("                                                                                                          ");
        tmpReqMsgHead.append(p_bankHeader.fourZero + "0                       0");

        // 消息报文
        String tmpReqData = tmpReqMsgHead + p_reqStr;
        WriteBankLogStep2(tmpReqData);

        TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(bankFront.serverPort), this);
        WriteBankLogLn("服务地址：[" + bankFront.serverIP + ":" + bankFront.serverPort + "]。");

        TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpReqData.getBytes(getCharset()));
        tmpStrRet[0] = tmpReceiver.connState;
        if (tmpReceiver.recBytes != null) {
            tmpStrRet[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, getCharset());
            if(tmpReceiver.recBytes.length > 93){
            	tmpStrRet[2]= new String(tmpReceiver.recBytes, 87, 6, getCharset());
            }
            if(tmpReceiver.recBytes.length > 193){
            	tmpStrRet[3] = StringHelper.trimStart(new String(tmpReceiver.recBytes, 93, 100, getCharset()).trim(), ":");
            }
            
        } else {
            tmpStrRet[1] = tmpReceiver.getConnMsg();
        }
        WriteBankLogStep3(tmpStrRet[1]);
        if (!tmpReceiver.isCompleted) {
            WriteBankLogLn(tmpReceiver.getConnMsg());
        }

        return tmpStrRet;
    }

    public void getContentLength(TcpReceiver p_receiver) throws Exception {
        if (p_receiver.contentLength == -1) {
            if (p_receiver.readedLength >= 222) {
                p_receiver.contentLength = Integer.parseInt(new String(p_receiver.recBytes, 30, 10, getCharset()));
                p_receiver.contentStartIndex = 222;
            }
        }
    }

    // 上送格式为json格式
    protected String[] sendToATS(String jsonData) throws Exception {
        String[] retStr = new String[] { "", "" };
        WriteBankLogLn("2.提交ATS的地址：" + FGBiz.dspCenter.dspSet.receiptPushServerUrl);

        // 发送银行前置
        WebRequest tmpRequest = new WebRequest(FGBiz.dspCenter.dspSet.receiptPushServerUrl);
        tmpRequest.setConnectTimeout(10000);
        tmpRequest.setRequestProperty("connection", "Close");
        tmpRequest.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        String charsetName = getCharset();
        StringBuilder data = new StringBuilder();
        data.append(jsonData);
        WriteBankLogLn("3.推送给ATS的数据" + data.toString());
        byte[] tmpWriteBytes = data.toString().getBytes(charsetName);
        retStr = tmpRequest.upload(tmpWriteBytes, charsetName);
        WriteBankLogLn("4.返回的数据" + retStr[1]);

        return retStr;
    }

    /**
     * 平安付商户充值1000000为1元
     * 乘以1000000，返回整数
     */
    public static String amountMultiply1000000(String p_yuan) {
        BigDecimal tmpDecAmt = new BigDecimal(p_yuan);
        tmpDecAmt = tmpDecAmt.multiply(new BigDecimal("1000000"));
        return tmpDecAmt.toBigInteger().toString();
    }
    /**
     * 将MAP转换为post请求串
     * @return
     */
    public String convertMapToStr(Map<String,Object> params) {
        String reqStr = "";
        for (String key : params.keySet()) {
            if (!params.get(key).equals("")) {
                if (reqStr.length() > 0) {
                    reqStr += "&";
                }
                reqStr += key + "=" + params.get(key);
            }
        }
        return reqStr;
    }
    /**
     * 签名入口
     *
     * @param origText
     * @param strPrivKey
     * @return
     */
    public static String sign(String origText, String strPrivKey) {
        String signature = "";
        try {
            // 用base64解码
            byte[] privKeyByte = Base64.decodeBase64(strPrivKey);
            // 私钥需要使用pkcs8格式的
            PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(privKeyByte);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PrivateKey privKey = kf.generatePrivate(privKeySpec);
            // 加签
            signature = Base64.encodeBase64String(signBase(origText.getBytes(Charset.forName("UTF-8")), privKey, "SHA1WithRSA"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return signature;
    }
    /**
     * ***********************************************************************************************
     * ** 用openssl产生的私钥签名
     *
     * @param text 用于签名数据
     * @param key openssl产生的私钥
     * @param instanceType 签名实例类型
     * @return Encrypted 签名
     */

    private static byte[] signBase(byte[] text, PrivateKey key, String instanceType) {
        byte[] signatureText = null;
        try {
            final Signature signature = Signature.getInstance(instanceType);
            signature.initSign(key);
            signature.update(text);
            signatureText = signature.sign();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return signatureText;
    }
    /**
     * @param content 加密前数据
     * @return
     * @description: AES加密算法入口
     */
    public static String encrypt4Aes(String content, String key, String charset) {
        try {
            byte[] src = content.getBytes(charset); // 加密
            byte[] bytOut = encryptMode(src, key);
            return base64encode(bytOut);
        } catch (Exception e3) {}
        return null;
    }
    /**
     * @param src 加密前数据字节 * @return
     * @description: AES加密实现
     */
    private static byte[] encryptMode(byte[] src, String key) {
        try {
            Cipher cip = Cipher.getInstance("AES");
            cip.init(Cipher.ENCRYPT_MODE, getSecretKey(key));
            return cip.doFinal(src);
        } catch (Exception e3) {}
        return null;
    }
    // 将 s 进行 BASE64 编码
    public static String base64encode(byte[] src) {
        if (src == null) {
            return null;
        }
        return (new sun.misc.BASE64Encoder()).encode(src);
    }
    private static SecretKey getSecretKey(String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
        byte[] keybyte = getKeyByStr(key);
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        secureRandom.setSeed(keybyte);
        KeyGenerator keygen = KeyGenerator.getInstance("AES");
        keygen.init(secureRandom);
        return keygen.generateKey();
    }

    private static byte[] getKeyByStr(String str) {
        byte[] bRet = new byte[str.length() / 2];
        for (int i = 0; i < str.length() / 2; i++) {
            Integer itg = new Integer(16 * getChrInt(str.charAt(2 * i)) + getChrInt(str.charAt(2 * i + 1)));
            bRet[i] = itg.byteValue();
        }
        return bRet;
    }
    public static int getChrInt(char chr) {
        int iRet = 0;
        if (chr == "0".charAt(0)) {
            iRet = 0;
        }
        if (chr == "1".charAt(0)) {
            iRet = 1;
        }
        if (chr == "2".charAt(0)) {
            iRet = 2;
        }
        if (chr == "3".charAt(0)) {
            iRet = 3;
        }
        if (chr == "4".charAt(0)) {
            iRet = 4;
        }
        if (chr == "5".charAt(0)) {
            iRet = 5;
        }
        if (chr == "6".charAt(0)) {
            iRet = 6;
        }
        if (chr == "7".charAt(0)) {
            iRet = 7;
        }
        if (chr == "8".charAt(0)) {
            iRet = 8;
        }
        if (chr == "9".charAt(0)) {
            iRet = 9;
        }
        if (chr == "A".charAt(0)) {
            iRet = 10;
        }
        if (chr == "B".charAt(0)) {
            iRet = 11;
        }
        if (chr == "C".charAt(0)) {
            iRet = 12;
        }


        if (chr == "D".charAt(0)) {
            iRet = 13;
        }
        if (chr == "E".charAt(0)) {
            iRet = 14;
        }
        if (chr == "F".charAt(0)) {
            iRet = 15;
        }
        return iRet;
    }
    /**
     * 对字符串加密,加密算法使用MD5,SHA-1,SHA-256,默认使用SHA-256
     *
     * @param strSrc 要加密的字符串
     * @param encName 加密类型
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String encryptPwd(String strSrc, String encName, String charset) throws UnsupportedEncodingException {
        MessageDigest md = null;
        String strDes = null;

        byte[] bt = strSrc.getBytes(charset);
        try {
            if (encName == null || encName.equals("")) {
                encName = "SHA-256";
            }
            md = MessageDigest.getInstance(encName);
            md.update(bt);
            strDes = bytes2Hex(md.digest()); // to HexString
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
        return strDes;
    }
    public static String bytes2Hex(byte[] bts) {
        String des = "";
        String tmp = null;
        for (int i = 0; i < bts.length; i++) {
            tmp = (Integer.toHexString(bts[i] & 0xFF));
            if (tmp.length() == 1) {
                des += "0";
            }
            des += tmp;
        }
        return des;
    }

    private static HttpClient HTTPCLIENT;
    private static HttpClient getHttpClient() {
        if (HTTPCLIENT == null) {
            synchronized (new Object()) {
                if (HTTPCLIENT == null) {
                    initHttpClient();
                }
            }
        }
        return HTTPCLIENT;
    }
    private static void initHttpClient() {

        BasicHttpClientConnectionManager connManager =
                new BasicHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", SSLConnectionSocketFactory.getSocketFactory()).build(), null, null, null);
        RequestConfig.Builder rBuilder = RequestConfig.custom();
        rBuilder.setSocketTimeout(10000).setConnectTimeout(10000).build();
        if (false) {
            // 代理设置
            HttpHost proxy = new HttpHost("10.189.6.187", 8080, "http");
            rBuilder.setProxy(proxy);
        }

        RequestConfig requestConfig = rBuilder.build();
        HTTPCLIENT = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).disableAutomaticRetries().setConnectionManager(connManager).build();
    }
    /**
     * AES算法解密入口
     */
    public static String decrypt4Aes2Str(String contentbase64, String key, String charset) {
        String Result = null;
        try {
            byte[] dst = decrypt4Aes(contentbase64, key);
            if (null != dst) {
                Result = new String(dst, charset);
            }
        } catch (Exception e3) {}
        return Result;
    }

    private static byte[] decrypt4Aes(String contentbase64, String key) {
        try {
            byte[] src = base64decode(contentbase64); // 解密
            return decryptMode(src, key);
        } catch (Exception e3) {}
        return null;
    }
    // 将 BASE64 编码的字符串 s 进行解码
    public static byte[] base64decode(String s) {
        if (s == null) {
            return null;
        }
        sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
        try {
            byte[] b = decoder.decodeBuffer(s);
            return b;
        } catch (Exception e) {
            return null;
        }
    }
    private static byte[] decryptMode(byte[] src, String key) {
        try {
            Cipher cip = Cipher.getInstance("AES");
            cip.init(Cipher.DECRYPT_MODE, getSecretKey(key));
            return cip.doFinal(src);
        } catch (Exception e3) {}
        return null;
    }
}
